from math import ceil

class Player:
	def __init__(self):
		# We only need to keep the number of hunts and the total number of hunts and slacks
		self.hunts = 0
		self.total = 0

	def hunt_choices(self, round_number, current_food, current_reputation, m, player_reputations):
		# The main idea is to try to approximate our reputation to the median of all the reputations
		#We also consider a prediction for how many hunts we have to make to achieve m, and try to incorporate it
		#into the decision, if it does not increase the reputation very much
		n = len(player_reputations) + 1

		# We need a list of sorted_reps in the future. It also helps us get the median
		#Note: this is a list of (reputation, original index) tuples
		sorted_reps = [(rep, i) for i, rep in enumerate(player_reputations)]
		sorted_reps = sorted(sorted_reps)

		# The median of all the reputations is used as our goal. Therefore, in the first round we consider
		#a goal of 0.6, while in the other rounds we calculate the median as is usually done.
		if self.total == 0:
			median = 0.6
		else:
			if (len(sorted_reps) % 2 == 1):
				median = sorted_reps[len(sorted_reps) / 2][0]
			else:
				median = 0.5*sorted_reps[len(sorted_reps) / 2][0] + 0.5*sorted_reps[len(sorted_reps) / 2 - 1][0]

		# We want our new reputation to be as close to 'median' as possible. Therefore, we solve
		#(self.hunts+next_hunts)/(self.total+(n-1)) >= median. This inequation represents: "we want 
		#the new reputation to be at least as large as the median
		next_hunts = int(ceil(1.0*median*(self.total+n-1)-self.hunts))

		# Our prediction is that each player hunts R*(n-1) times, that is, each player hunts in proportion
		#with the value of R. 'prediction' represents the sum of all these values, which is our prediction for
		#the total number of hunts for all players except ourselves.
		prediction = sum([rep * (n-1) for rep in player_reputations])
		# Therefore, to reach 'm' hunts, we need to hunt 'hunts_needed' times
		hunts_needed = m - prediction
		# To be safe, we add some hunts to compensate for non-cooperative players
		hunts_corrected = int(ceil(hunts_needed+0.1*n))
		# We do not allow the reputation to exceed both the previous reputation and 1.05 times the goal
		#This allows us to establish a limit to prevent the increase of the reputation when it is not desired.
		if self.total == 0:
			max_rep = 1.05*median
		else:
			max_rep = max(1.0*self.hunts/self.total, 1.05*median)
		if 1.0*(self.hunts+hunts_corrected)/(self.total+n-1) > max_rep: # The new reputation exceeds the limit
			hunts_corrected = int(max_rep*(self.total+n-1)-self.hunts)  # Correct the value to be within expectation
		# If too many are needed, we disregard the case (or if it is the first round)
		if self.total == 0 or hunts_needed > n-1:
			hunts_corrected = 0

		# If we were already doing at least 'hunts_corrected' hunts, then we do not need to change anything
		# However, if we were not, we adjust 'next_hunts' to be at least equal to 'hunts_corrected'
		if (hunts_corrected > next_hunts):
			next_hunts = hunts_corrected

		# Of course, we cannot have more than 'n-1' hunts or less than 0.
		if next_hunts > n-1:
			next_hunts = n-1
		elif next_hunts < 0:
			next_hunts = 0

		# Start with 'n-1' hunts, and then set it to 's' for the most slackers
		hunt_decisions = ['h']*(n-1)
		for i in xrange(n-1-next_hunts):
			hunt_decisions[sorted_reps[i][1]] = 's'

		self.total += len(hunt_decisions)
		self.hunts += sum([1 for hunt in hunt_decisions if hunt == 'h'])

		return hunt_decisions

	def hunt_outcomes(self, food_earnings):
		pass # do nothing

	def round_end(self, award, m, number_hunters):
		pass # do nothing
